using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Management;
using Microsoft.Win32;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace IppPrinterInstallHelper
{
    internal sealed class DriverSelectionForm : Form
    {
        private readonly ListBox _manufacturerList;
        private readonly ListBox _driverList;
        private readonly Button _windowsUpdateButton;
        private readonly Button _haveDiskButton;
        private readonly Button _okButton;
        private readonly Button _cancelButton;

        private readonly Dictionary<string, List<string>> _driversByManufacturer =
            new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);

        public string SelectedDriverName { get; private set; }

        public DriverSelectionForm()
        {
            Text = "添加打印机向导";
            StartPosition = FormStartPosition.CenterParent;
            FormBorderStyle = FormBorderStyle.FixedDialog;
            MaximizeBox = false;
            MinimizeBox = false;
            // 调整窗口大小，更接近 Windows 原生窗口
            ClientSize = new Size(680, 450);

            var titleLabel = new Label
            {
                AutoSize = false,
                Text = "选择制造商和打印机型号。如果打印机有安装磁盘，请单击“从磁盘安装”。如果你的打印机未列出，请查阅打印机文档以获得兼容打印机。",
                Location = new Point(20, 20),
                Size = new Size(640, 50)
            };

            var manufacturerLabel = new Label
            {
                AutoSize = true,
                Text = "厂商",
                Location = new Point(20, 85)
            };

            var printerLabel = new Label
            {
                AutoSize = true,
                Text = "打印机",
                Location = new Point(250, 85)
            };

            _manufacturerList = new ListBox
            {
                Location = new Point(20, 105),
                Size = new Size(220, 240)
            };
            _manufacturerList.SelectedIndexChanged += ManufacturerList_SelectedIndexChanged;

            _driverList = new ListBox
            {
                Location = new Point(250, 105),
                Size = new Size(410, 240)
            };

            _windowsUpdateButton = new Button
            {
                Text = "Windows 更新(&W)",
                Location = new Point(420, 355),
                Size = new Size(120, 26)
            };
            _windowsUpdateButton.Click += WindowsUpdateButton_Click;

            _haveDiskButton = new Button
            {
                Text = "从磁盘安装(&H)...",
                Location = new Point(540, 355),
                Size = new Size(120, 26)
            };
            _haveDiskButton.Click += HaveDiskButton_Click;

            // 添加驱动签名提示区域（模仿 Windows 原生窗口）
            var signatureIcon = new PictureBox
            {
                Location = new Point(20, 360),
                Size = new Size(16, 16),
                SizeMode = PictureBoxSizeMode.StretchImage
            };
            try
            {
                signatureIcon.Image = SystemIcons.Shield.ToBitmap();
            }
            catch
            {
            }

            var signatureLabel = new Label
            {
                AutoSize = true,
                Text = "这个驱动程序已经过数字签名。",
                Location = new Point(40, 360)
            };

            var signatureLink = new LinkLabel
            {
                AutoSize = true,
                Text = "告诉我为什么驱动程序签名很重要",
                Location = new Point(20, 380),
                LinkBehavior = LinkBehavior.HoverUnderline
            };
            signatureLink.LinkClicked += (s, e) =>
            {
                try
                {
                    System.Diagnostics.Process.Start("https://support.microsoft.com/zh-cn/windows");
                }
                catch
                {
                }
            };

            _okButton = new Button
            {
                Text = "确定",
                DialogResult = DialogResult.OK,
                Location = new Point(500, 410),
                Size = new Size(75, 26)
            };
            _okButton.Click += OkButton_Click;

            _cancelButton = new Button
            {
                Text = "取消",
                DialogResult = DialogResult.Cancel,
                Location = new Point(585, 410),
                Size = new Size(75, 26)
            };

            Controls.Add(titleLabel);
            Controls.Add(manufacturerLabel);
            Controls.Add(printerLabel);
            Controls.Add(_manufacturerList);
            Controls.Add(_driverList);
            Controls.Add(_windowsUpdateButton);
            Controls.Add(_haveDiskButton);
            Controls.Add(signatureIcon);
            Controls.Add(signatureLabel);
            Controls.Add(signatureLink);
            Controls.Add(_okButton);
            Controls.Add(_cancelButton);

            AcceptButton = _okButton;
            CancelButton = _cancelButton;

            Load += DriverSelectionForm_Load;
        }

        private void DriverSelectionForm_Load(object sender, EventArgs e)
        {
            LoadDrivers();
        }

        private void LoadDrivers()
        {
            _manufacturerList.Items.Clear();
            _driverList.Items.Clear();
            _driversByManufacturer.Clear();

            // 1. 优先从注册表中枚举已安装的打印机驱动
            try
            {
                LoadDriversFromRegistry(@"SYSTEM\CurrentControlSet\Control\Print\Environments\Windows x64\Drivers\Version-3");
                LoadDriversFromRegistry(@"SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86\Drivers\Version-3");
            }
            catch
            {
            }

            // 2. 从 INF 文件中解析所有可用的打印机驱动（这是关键，能获取到系统内置的所有驱动）
            try
            {
                LoadDriversFromInfFiles();
            }
            catch
            {
            }

            // 3. 如果以上方式都失败，再退回到 WMI（有些环境可能只在 WMI 中可见）
            if (_driversByManufacturer.Count == 0)
            {
                try
                {
                    var searcher = new ManagementObjectSearcher("SELECT Name, DriverProviderName FROM Win32_PrinterDriver");
                    foreach (ManagementObject obj in searcher.Get())
                    {
                        var name = (obj["Name"] as string) ?? string.Empty;
                        var provider = (obj["DriverProviderName"] as string) ?? "其它";

                        AddDriver(provider, name);
                    }
                }
                catch
                {
                    // 忽略获取驱动列表时的错误
                }
            }

            foreach (var kv in _driversByManufacturer.OrderBy(k => k.Key))
            {
                kv.Value.Sort(StringComparer.OrdinalIgnoreCase);
                _manufacturerList.Items.Add(kv.Key);
            }

            if (_manufacturerList.Items.Count > 0)
            {
                _manufacturerList.SelectedIndex = 0;
            }
        }

        private void LoadDriversFromRegistry(string subKeyPath)
        {
            using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
            using (var driversKey = baseKey.OpenSubKey(subKeyPath))
            {
                if (driversKey == null)
                {
                    return;
                }

                foreach (var driverKeyName in driversKey.GetSubKeyNames())
                {
                    using (var driverKey = driversKey.OpenSubKey(driverKeyName))
                    {
                        if (driverKey == null) continue;

                        var name = (driverKey.GetValue("Name") as string) ?? driverKeyName;
                        var provider = (driverKey.GetValue("Provider") as string) ?? "其它";

                        AddDriver(provider, name);
                    }
                }
            }
        }

        private void LoadDriversFromInfFiles()
        {
            var infDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "INF");
            if (!Directory.Exists(infDir))
            {
                return;
            }

            var infFiles = Directory.GetFiles(infDir, "*.inf", SearchOption.TopDirectoryOnly);
            foreach (var infFile in infFiles)
            {
                try
                {
                    ParseInfFile(infFile);
                }
                catch
                {
                    // 忽略单个 INF 文件解析错误
                }
            }
        }

        private void ParseInfFile(string infPath)
        {
            var lines = File.ReadAllLines(infPath);
            var inManufacturerSection = false;
            var manufacturerMap = new Dictionary<string, string>(); // 厂商ID -> 厂商显示名
            var currentManufacturerId = string.Empty;

            for (int i = 0; i < lines.Length; i++)
            {
                var line = lines[i].Trim();
                if (string.IsNullOrEmpty(line) || line.StartsWith(";", StringComparison.Ordinal))
                {
                    continue;
                }

                // 检测 [Manufacturer] 段
                if (line.Equals("[Manufacturer]", StringComparison.OrdinalIgnoreCase))
                {
                    inManufacturerSection = true;
                    continue;
                }

                if (inManufacturerSection)
                {
                    // 如果遇到新的段，结束 [Manufacturer] 段
                    if (line.StartsWith("[", StringComparison.Ordinal))
                    {
                        inManufacturerSection = false;
                        // 继续处理厂商段
                        if (manufacturerMap.ContainsValue(line.Trim('[', ']')))
                        {
                            currentManufacturerId = line.Trim('[', ']');
                            ParseManufacturerSection(lines, i, currentManufacturerId, manufacturerMap);
                        }
                        continue;
                    }

                    // 解析 Manufacturer 行： "Pantum"=Pantum 或 "Pantum"="Pantum"
                    var match = Regex.Match(line, @"^""([^""]+)""\s*=\s*([^\s,]+)", RegexOptions.IgnoreCase);
                    if (match.Success)
                    {
                        var displayName = match.Groups[1].Value;
                        var manufacturerId = match.Groups[2].Value.Trim('"');
                        manufacturerMap[manufacturerId] = displayName;
                    }
                }
            }

            // 如果文件结构不同，尝试直接查找所有 [厂商ID] 段
            foreach (var kv in manufacturerMap)
            {
                for (int i = 0; i < lines.Length; i++)
                {
                    if (lines[i].Trim().Equals($"[{kv.Key}]", StringComparison.OrdinalIgnoreCase))
                    {
                        ParseManufacturerSection(lines, i, kv.Key, manufacturerMap);
                        break;
                    }
                }
            }
        }

        private void ParseManufacturerSection(string[] lines, int startIndex, string manufacturerId, Dictionary<string, string> manufacturerMap)
        {
            if (!manufacturerMap.TryGetValue(manufacturerId, out var manufacturerName))
            {
                manufacturerName = manufacturerId;
            }

            for (int i = startIndex + 1; i < lines.Length; i++)
            {
                var line = lines[i].Trim();
                if (string.IsNullOrEmpty(line) || line.StartsWith(";", StringComparison.Ordinal))
                {
                    continue;
                }

                // 如果遇到新的段，结束当前段
                if (line.StartsWith("[", StringComparison.Ordinal))
                {
                    break;
                }

                // 解析驱动行： "Pantum M6200 Series" = PANTUM_M6200_SERIES.GPD
                var match = Regex.Match(line, @"^""([^""]+)""", RegexOptions.IgnoreCase);
                if (match.Success)
                {
                    var driverName = match.Groups[1].Value;
                    AddDriver(manufacturerName, driverName);
                }
            }
        }

        private void AddDriver(string provider, string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                return;
            }

            // 某些 Name 形如 "Pantum M6200W Series,winspool,Ne00:"，取逗号前部分
            var commaIndex = name.IndexOf(',');
            if (commaIndex > 0)
            {
                name = name.Substring(0, commaIndex);
            }
            name = name.Trim();
            if (string.IsNullOrEmpty(name))
            {
                return;
            }

            if (string.IsNullOrWhiteSpace(provider))
            {
                provider = "其它";
            }

            if (!_driversByManufacturer.TryGetValue(provider, out var list))
            {
                list = new List<string>();
                _driversByManufacturer[provider] = list;
            }
            if (!list.Contains(name, StringComparer.OrdinalIgnoreCase))
            {
                list.Add(name);
            }
        }

        private void ManufacturerList_SelectedIndexChanged(object sender, EventArgs e)
        {
            _driverList.Items.Clear();

            if (_manufacturerList.SelectedItem == null)
            {
                return;
            }

            var manufacturer = _manufacturerList.SelectedItem.ToString();
            if (_driversByManufacturer.TryGetValue(manufacturer, out var list))
            {
                foreach (var d in list)
                {
                    _driverList.Items.Add(d);
                }
                if (_driverList.Items.Count > 0)
                {
                    _driverList.SelectedIndex = 0;
                }
            }
        }

        private void WindowsUpdateButton_Click(object sender, EventArgs e)
        {
            try
            {
                // 调用系统原生的“添加打印机”向导，用户可以在其中使用 Windows 更新功能
                // /im 打开完整的添加打印机窗口，用户可以在其中选择“Windows 更新”选项
                var psi = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "rundll32.exe",
                    Arguments = "printui.dll,PrintUIEntry /im",
                    UseShellExecute = true
                };
                System.Diagnostics.Process.Start(psi);
            }
            catch (Exception ex)
            {
                MessageBox.Show(this,
                    $"无法打开系统添加打印机向导：\n{ex.Message}",
                    "错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void HaveDiskButton_Click(object sender, EventArgs e)
        {
            try
            {
                // 调用系统原生的“添加打印机驱动程序向导”
                // /s . 指定本地服务器，/ia 打开添加打印机驱动程序向导
                var psi = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "rundll32.exe",
                    Arguments = "printui.dll,PrintUIEntry /s . /ia",
                    UseShellExecute = true
                };
                System.Diagnostics.Process.Start(psi);
            }
            catch (Exception ex)
            {
                MessageBox.Show(this,
                    $"无法打开“从磁盘安装”向导：\n{ex.Message}",
                    "错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void OkButton_Click(object sender, EventArgs e)
        {
            if (_driverList.SelectedItem == null)
            {
                MessageBox.Show(this, "请选择一个打印机型号。", "提示",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                DialogResult = DialogResult.None;
                return;
            }

            SelectedDriverName = _driverList.SelectedItem.ToString();
        }
    }
}


